home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 September / macformat-004.iso / Shareware City / Graphics / VideoToolbox ƒ / VideoToolboxSources / GDOpenWindow.c < prev    next >
Encoding:
Text File  |  1994-07-07  |  9.3 KB  |  229 lines  |  [TEXT/KAHL]

  1. /* GDOpenWindow.c
  2. Copyright © 1989-1994 Denis G. Pelli
  3.  
  4. SUMMARY:
  5.  
  6. AddExplicitPalette(window) adds a palette to a color window or GWorld with all the
  7. colors marked as pmExplicit. This allows you to use PmForeColor() and
  8. PmBackColor() to specify the value you want poked into each pixel by QuickDraw
  9. operations, e.g. EraseRect() and DrawString(). It also now calls
  10. MakeColorTableExplicit(), which causes CopyBits to faithfully copy
  11. your pixels as numbers, without color translation, when you copy from your window.
  12.  
  13. RemovePalette(window) disposes of the palette created by AddExplicitPalette.
  14.  
  15. window=GDOpenWindow1(device) opens a full-screen window on the specified screen,
  16. and calls AddExplicitPalette. The window truly fills the screen: any rounded
  17. corners are made square and if the window is on the main screen then the Menu
  18. Bar is hidden. The screen occupies the content area of the window; the window's
  19. frame (one-pixel black line border and title bar) is off that screen, but will
  20. appear on other screens that form contiguous parts of your desktop. The elegant
  21. solution to this, which perhaps someone will implement, would be to define a new
  22. window type that has no frame.
  23.  
  24. GDDisposeWindow1(window) closes and discards a color window, disposing of any palette
  25. or color table, generally undoing whatever GDOpenWindow1 did.
  26.  
  27. These routines return and accept a WindowPtr (even though it's actually
  28. a color window), which seems to be the standard way of doing things. 
  29. The older routines, without the "1" suffix, return and accept a CWindowPtr,
  30. which ends up forcing you to do a lot of tedious casting, e.g. when you call
  31. SetPort(), which wants a WindowPtr.
  32.  
  33. COMMENTS:
  34.  
  35. QuickDraw likes to pick a bunch of good colors and stuff them in the clut, in
  36. essentially random order, except that white is first and black is last. It wants
  37. you to specify any desired color as an RGB triplet and then it picks the mysterious
  38. clut index that would provide the closest match. If you're processing grayscale
  39. images, then QuickDraw's approach involves a lot of overhead involving inverse
  40. color tables, and makes the numbers stored in your pixels meaningless (unless
  41. you look them up in the associated color table or palette).
  42.  
  43. The philosophy of the VideoToolbox is to bypass QuickDraw's color model, and
  44. work explicitly with the numbers that are stored in your pixels.
  45. SetPixelsQuickly will efficiently poke (or peek) numbers in your PixMap.
  46. However, if you want to use QuickDraw's drawing operations, especially
  47. EraseRect() and DrawString() then you need a way to specify the foreground and
  48. background colors. AddExplicitPalette() gives your window a palette in which all
  49. the colors are marked as pmExplicit. This tells the palette manager not to
  50. meddle, and to use your arguments to PmForeColor() and PmBackColor() literally.
  51.  
  52. I suggest that you control the clut by calling GDUncorrectedGamma() and
  53. GDSetEntries(), since these calls directly control the video device driver,
  54. bypassing the Color Manager. Since the Color and Palette Managers don't know
  55. that you've changed the color environment they can't react to it, and will
  56. passively let you continue to specify colors by their clut index. For example,
  57. the Palette Manager religiously believes that the first clut entry should be
  58. white and the last one black, and it will change them back to those values if
  59. you change them and it finds out about it. If you use the Color Manager
  60. SetEntries call then the Paletter Manger WILL find out because a record is made
  61. in the ColorTable. Calling GDSetEntries() bypasses the Color Manager. Instead,
  62. the video device driver writes directly to the clut and the ColorTable is not
  63. modified. Of course, this means that you should ignore the ColorTable since it
  64. will no longer reflect the contents of the clut.
  65.  
  66. Every time you access the stdio package, e.g. printf or getch(), THINK C will
  67. move the Console window to the front, which may obscure your window. You can
  68. bring your window back to the front by calling BringToFront().
  69.  
  70. EXAMPLE:
  71.  
  72. Open your window by saying:
  73.     window=GDOpenWindow1(device);
  74. When you're through with the window, get rid of it by calling:
  75.     GDDisposeWindow1(window);
  76. Besides closing the window and disposing of the allocated memory structures
  77. GDDisposeWindow1 also restores the device's clut to whatever is in the color 
  78. table associated with device.
  79.  
  80. HISTORY:
  81.  
  82. 12/88        dgp    wrote it
  83. 8/5/89            added call to GDUncorrectedGamma, so I couldn't forget.
  84. 8/15/89     dgp trivia
  85. 3/20/90        dgp    make compatible with MPW C.
  86. 3/29/90        dgp    changed declared returned type from WindowPtr to CWindowPtr, which
  87.                 is what it's really been all along. Same change to argument of
  88.                 GDDisposeWindow(). The new offscreen GWorld calls for the first time
  89.                 make it easier to honestly declare one's windows as color rather
  90.                 than pretending they're not.
  91. 8/24/91        dgp    Made compatible with THINK C 5.0.
  92. 2/1/92        dgp Made optional the device argument to GDDisposeWindow(). If it's
  93.                 NULL, then it will be determined automatically from window.
  94. 2/3/93        dhb    Extracted AddExplicitPalette from GDOpenWindow.
  95. 2/21/93        dgp    HideMenuBar if window is on main screen.
  96. 2/23/93        dgp AddExplicitPalette() returns immediately unless it receives a color 
  97.                 window.
  98.                 Added GDOpenWindow1() and GDDisposeWindow1(), which both use
  99.                 a WindowPtr, instead of a less convenient CWindowPtr.
  100. 3/5/93        dgp    Added calls to UnclipScreen() and RestoreScreenClipping(), so the window
  101.                 now truly fills the whole screen. Edited GDOpenWindow() for clarity.
  102. 3/7/83        dgp    Added calls to GDSaveGamma(device) and GDRestoreGamma(device).
  103. 4/16/93        dgp    Cosmetic editing.
  104. 5/22/93        dgp    Added RemovePalette(), but didn't test it.
  105. 1/27/94        dgp    Cosmetic editing.
  106. 3/5/94        dgp    Decided that RemovePalette() works fine now.
  107. 6/8/94        dgp AddExplicitPalette now calls the new MakeColorTableExplicit(), which
  108.                 sets the Color Table ctFlags to indicate that
  109.                 the Color Table refers explicitly
  110.                 to the explicit palette. This tells CopyBits to treat
  111.                 the pixels as numbers, not indices.
  112. 6/13/94        dgp In response to query by David Brainard I now document above
  113.                 the obscure fact that GDOpenWindow's frame will appear on
  114.                 other screens that are contiguous parts of the desktop.
  115. */
  116. #include "VideoToolbox.h"
  117.  
  118. #define MAKE_COLOR_TABLE 0
  119.  
  120. CWindowPtr GDOpenWindow(GDHandle device)
  121. // Obsolete. Use GDOpenWindow1 instead.
  122. {
  123.     return (CWindowPtr)GDOpenWindow1(device);
  124. }
  125.  
  126. void GDDisposeWindow(GDHandle device,CWindowPtr window)
  127. // Obsolete. Use GDDisposeWindow1 instead.
  128. {
  129.     GDDisposeWindow1((WindowPtr) window);
  130. }
  131.  
  132.  
  133. WindowPtr GDOpenWindow1(GDHandle device)
  134. {
  135.     WindowPtr window;
  136.     Rect r;
  137.     GDHandle oldDevice;
  138.  
  139.     if(device==NULL)return NULL;
  140.     r=(*device)->gdRect;        // rect of desired screen in global coordinates
  141.     GDSaveGamma(device);
  142.     GDUncorrectedGamma(device);
  143.     UnclipScreen(device);
  144.     oldDevice=GetGDevice();
  145.     SetGDevice(GetMainDevice());
  146.     window=(WindowPtr)NewCWindow(NULL,&r,"\pHi",TRUE,plainDBox,(WindowPtr) -1L,0,123L);
  147.     SetGDevice(oldDevice);
  148.     AddExplicitPalette(window);
  149.     return window;
  150. }
  151.  
  152. void GDDisposeWindow1(WindowPtr window)
  153. // Dispose of window and palette and restore the clut.
  154. {
  155.     GDHandle device;
  156.     
  157.     if(window==NULL)return;
  158.     device=GetWindowDevice(window);
  159.     DisposePalette(GetPalette(window));
  160.     #if MAKE_COLOR_TABLE
  161.         DisposHandle((Handle)(*((CGrafPtr)window)->portPixMap)->pmTable);
  162.     #endif
  163.     DisposeWindow(window);
  164.     if(device==NULL)return;
  165.     GDRestoreGamma(device);
  166.     GDRestoreDeviceClut(device);
  167.     RestoreScreenClipping(device);
  168. }
  169.  
  170. void MakeColorTableExplicit(CWindowPtr window)
  171. {
  172.     int i,ok;
  173.     CTabHandle ct;
  174.  
  175.     // If it's a GWorldPtr then we must lock the pixels to access the pixmap.
  176.     if((window->portVersion&0xc001)==0xc001){
  177.         ok=LockPixels(GetGWorldPixMap(window));
  178.         if(!ok)return;
  179.     }
  180.     // As per IM-VI-20-17, let's link the Color Table to the palette.
  181.     ct=(*window->portPixMap)->pmTable;
  182.     (*ct)->ctFlags|=0x4000;
  183.     for(i=(*ct)->ctSize;i>=0;i--)(*ct)->ctTable[i].value=i;
  184. }
  185.  
  186. void AddExplicitPalette(WindowPtr window)
  187. // Create a palette for the color window and mark all the entries as explicit.
  188. // Copy the entries from the window's device.
  189. {
  190.     GDHandle device;
  191.     CTabHandle ct;
  192.     PaletteHandle palette;
  193.     int colors,i;
  194.     OSErr error;
  195.  
  196.     if(window==NULL)return;
  197.     if(((CGrafPtr)window)->portVersion>=0) return;    // Not a color window, return.
  198.     device=GetWindowDevice(window);
  199.     if(device==NULL)PrintfExit(
  200.         "%s line %d. AddExplicitPalette: window has no device!\n",__FILE__,__LINE__);
  201.     ct=(**(**device).gdPMap).pmTable;
  202.     colors=(*ct)->ctSize+1;
  203.     #if MAKE_COLOR_TABLE
  204.         error=HandToHand((Handle *)&ct);
  205.         if(error)PrintfExit("%s line %d: error %d in copying color table\n"
  206.             ,__FILE__,__LINE__,error);
  207.         (*ct)->ctFlags &= 0x7fff;    // clear "device" bit
  208.         for(i=0;i<colors;i++) (*ct)->ctTable[i].value=i;
  209.         (*ct)->ctSeed=GetCTSeed();
  210.         (*((CGrafPtr)window)->portPixMap)->pmTable=ct;
  211.     #endif
  212.     palette=NewPalette(colors,ct,pmExplicit,0);
  213.     SetPalette(window,palette,0);
  214.     MakeColorTableExplicit((CWindowPtr)window);
  215. }
  216.  
  217. void RemovePalette(WindowPtr window)
  218. {
  219.     DisposePalette(GetPalette(window));
  220. }
  221. /*
  222. RemovePalette may look dangerous. I worried that the Window or
  223. Palette Manager might become confused if it later tries to access the
  224. window's palette, which no longer exists. However, by trial and error
  225. I've found that this works fine, and that my attempts to make explicit the
  226. fact that the palette is gone, e.g. by calling SetPalette(window,NULL,0),
  227. all produced crashes. I conclude that the Palette or Window Manager monitors
  228. the calls to DisposePalette and thus knows that the palette is gone.
  229. */